<template>
  <div>
    <el-drawer :visible="show" :before-close="handleClose" size="500px" title="添加服务" append-to-body :wrapperClosable="false" custom-class='service-item-edit'>
    <el-scrollbar class="server-item-list">
      <el-form :rules="rules" :model='formData' ref='serviceForm' label-position='top' class="service-form">
        <el-form-item label='名称' prop="metaModelId">
          <el-popover placement="top" width="262" :value="showServiceDetail" trigger="manual">
            <div>identifier: {{ serviceItem.identifier }}</div>
            <div>id: {{ serviceItem.id }}</div>
            <div>name: {{ serviceItem.name }}</div>
            <div v-if='serviceItem.interfaceBid'>interfaceBid: {{ serviceItem.interfaceBid }}</div>
            <div v-if='serviceItem.serviceBid'>serviceBid: {{ serviceItem.serviceBid }}</div>
            <div slot="reference" @mouseenter="showServiceDetail = !!serviceItem.identifier" @mouseleave='showServiceDetail = false' @click="showServiceDetail = false">
              <treeselect v-model="formData.metaModelId" :options="options" :normalizer="normalizer" @select="handleChange" :disableFuzzyMatching="true" :clearable="false" placeholder="请选择" :disable-branch-nodes="true"/>
            </div>
          </el-popover>
        </el-form-item>
        <div v-for="(item, index) in formData.inputParams" :key="item.paramKey">
          <div v-if="item.allowEdit">
            <div v-if="item.category === 'Struct'">
              <struct-item :item='item' :componentsProps='componentsProps' ref="structItem"></struct-item>
            </div>
            <!-- 非结构体，UI样式要求与结构体不同，否则也可沿用上面结构体组件 -->
            <div v-else v-for="(member, mIndex) in item.memberList" :key="member.id">
              <div class="params-item">
                <el-form-item v-if="item.hasRefSignal && !member.specs && member.category !== 'String' && member.category !== 'Struct'" :prop="`inputParams[${index}].memberList[${mIndex}].calcRelation`" class="params-item-form setting-select" required>
                  <span slot='label' class="setting-select-label">{{ item.paramName }}</span>
                  <el-select v-model="member.calcRelation" placeholder="请选择" class="select-type" ref='selectCalc' @blur="hideCalc">
                    <el-option label="设置为" value="1"></el-option>
                    <el-option label="增加" value="2"></el-option>
                    <el-option label="减少" value="3"></el-option>
                  </el-select>
                </el-form-item>
                <el-popover v-if="componentsProps[member.id + member.paramKey] && componentsProps[member.id + member.paramKey].widgetClassName === 'Radio'" placement="bottom" width="262" trigger="click">
                  <el-radio-group v-model="member.value">
                    <el-radio v-for="option in member.specs" :label="option.key" :key="option.key" class="service-value-radio-item">{{ option.name }}</el-radio>
                  </el-radio-group>
                  <el-form-item slot="reference" :label='item.paramName' class="params-item-form" :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.select">
                    <el-input :value="member.specs.find(item => item.key === member.value) && member.specs.find(item => item.key === member.value).name" ref="serviceInput"></el-input>
                  </el-form-item>
                </el-popover>
                <el-popover v-else-if="componentsProps[member.id + member.paramKey] && componentsProps[member.id + member.paramKey].widgetClassName === 'RadioButton'" placement="bottom" width="262" trigger="click">
                  <el-radio-group v-model="member.value" :fill='componentsProps[member.id + member.paramKey].radioGroup_fill'>
                    <el-radio-button v-for="option in member.specs" :label="option.key" :key="option.key">{{ option.name }}</el-radio-button>
                  </el-radio-group>
                  <el-form-item slot="reference" :label='item.paramName' class="params-item-form" :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.select">
                    <el-input :value="member.specs.find(item => item.key === member.value) && member.specs.find(item => item.key === member.value).name" ref="serviceInput"></el-input>
                  </el-form-item>
                </el-popover>
                <el-popover v-else-if="componentsProps[member.id + member.paramKey] && componentsProps[member.id + member.paramKey].widgetClassName === 'Slider'" placement="bottom" width="262" trigger="click">
                  <el-slider
                    v-model="member.value"
                    :min='computeEdge(componentsProps[member.id + member.paramKey], member, "min")'
                    :max='computeEdge(componentsProps[member.id + member.paramKey], member, "max")'
                    :show-stops='componentsProps[member.id + member.paramKey].showStops'
                    :step='componentsProps[member.id + member.paramKey].step'></el-slider>
                  <el-form-item slot="reference" class="params-item-form" :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.input">
                    <el-input :value="member.value" ref="serviceInput"></el-input>
                    <el-popover v-if="member.discreteStr" placement="bottom-end" width="200" trigger="hover" :content="member.discreteStr" class="input-description" popper-class='desc-poper'>
                      <svg-icon slot="reference" icon-class="说明"/>
                    </el-popover>
                  </el-form-item>
                </el-popover>
                <el-popover v-else-if="componentsProps[member.id + member.paramKey] && componentsProps[member.id + member.paramKey].widgetClassName === 'Switch'" placement="bottom" width="262" trigger="click">
                  <el-switch
                    v-model="member.value"
                    :active-text="member.specs.find(item => item.key === 'true').name"
                    :inactive-text="member.specs.find(item => item.key === 'false').name"
                    :active-value='componentsProps[member.id + member.paramKey].activeValue'
                    :inactive-value='componentsProps[member.id + member.paramKey].inactiveValue'
                    :active-color='componentsProps[member.id + member.paramKey].activeColor'
                    :inactive-color='componentsProps[member.id + member.paramKey].inactiveColor'>
                  </el-switch>
                  <el-form-item slot="reference" :label='item.paramName' class="params-item-form" :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.select">
                    <el-input :value="member.specs.find(item => item.key === member.value) && member.specs.find(item => item.key === member.value).name" ref="serviceInput"></el-input>
                  </el-form-item>
                </el-popover>
                <el-form-item v-else-if="componentsProps[member.id + member.paramKey] && componentsProps[member.id + member.paramKey].widgetClassName === 'ColorPicker'" :label='item.paramName' class="params-item-form" prop="value" :rules="rules.select">
                  <el-color-picker v-model="member.value"></el-color-picker>
                </el-form-item>
                <el-form-item v-else-if="member.specs" :label='item.paramName' :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.select" class="params-item-form">
                  <el-select v-model="member.value" :filterable='componentsProps[member.id + member.paramKey] ? componentsProps[member.id + member.paramKey].filterable : undefined' placeholder="请选择">
                    <el-option v-for="option in member.specs" :key="option.key" :label="option.name" :value="option.key"></el-option>
                  </el-select>
                </el-form-item>
                <el-form-item v-else-if="member.category === 'String'" :label='item.paramName' :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.input" class="params-item-form">
                  <el-input v-model="member.value" placeholder="请输入"></el-input>
                  <el-popover v-if="member.discreteStr" placement="bottom-end" width="200" trigger="hover" :content="member.discreteStr" class="input-description" popper-class='desc-poper'>
                    <svg-icon slot="reference" icon-class="说明"/>
                  </el-popover>
                </el-form-item>
                <el-form-item v-else :prop="`inputParams[${index}].memberList[${mIndex}].value`" :rules="rules.input" class="params-item-form" :label="item.hasRefSignal ? undefined : item.paramName">
                  <el-input-number v-model="member.value" :min="computeEdge(componentsProps[member.id + member.paramKey], member, 'min')"  :max='computeEdge(componentsProps[member.id + member.paramKey], member, "max")' :precision="componentsProps[member.id + member.paramKey] ? componentsProps[member.id + member.paramKey].precision : undefined" placeholder="请输入" :controls='false' class="input-number"></el-input-number>
                  <el-popover v-if="member.discreteStr" placement="bottom-end" width="200" trigger="hover" :content="member.discreteStr" class="input-description" popper-class='desc-poper'>
                    <svg-icon slot="reference" icon-class="说明"/>
                  </el-popover>
                </el-form-item>
                <div class="tool-bar">
                  <svg-icon :icon-class="`参数${member.openParam.isOpen ? '已' : '未'}开放`" :className="`${member.openParam.isOpen} signal-open`" @click="paramOpen(member)"/>
                </div>
              </div>
              <ParamOpen :show.sync='member.showParamOpen' :openParam.sync='member.openParam' :signalItem.sync='item.memberList[mIndex]' ref='paramOpen'></ParamOpen>
            </div>
          </div>
        </div>
      </el-form>
    </el-scrollbar>
      <div class="service-edit-footer">
        <el-button type="primary" @click="saveEdit">保存</el-button>
      </div>
    </el-drawer>
  </div>
</template>

<script>
import ServiceNodeApi from '@/api/ruleNode/serviceNode'
import Platform from '@/utils/platform'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { adapterServiceItemData, formatComponentsProp } from '../serviceNode.util'
import ParamOpen from './paramOpen.vue'
import StructItem from './structItem.vue'
import { deepClone } from '@/utils/helper/jsUtil'
import { mapActions } from 'vuex'
export default {
  name: 'EditService',
  components: {
    ParamOpen,
    StructItem,
    Treeselect
  },
  data() {
    return {
      formData: {
        metaModelId: null,
        serviceName: '',
        serviceKey: '',
        inputParams: []
      },
      componentsProps: {},
      options: [],
      rules: {
        metaModelId: [{ required: true, message: '请选择', trigger: 'change' }],
        select: [{ required: true, message: ' ', trigger: 'change' }],
        input: [{ required: true, message: ' ', trigger: 'blur' }]
      },
      serviceItem: {},
      showServiceDetail: false
    }
  },
  props: {
    serviceData: {
      required: false,
      type: Object,
      default: () => {}
    },
    show: {
      required: true,
      type: Boolean,
      default: false
    }
  },
  mounted() {
    this.getGacMetaServices()
  },
  methods: {
    async getGacMetaServices() {
      const res = await this.getService()
      this.formatTree(res.data.options)
      this.serviceListData = res.data
      this.options = res.data.options
    },
    formatTree(list) {
      list.forEach(item => {
        item.value = item.id
        item.label = item.name
        if (item.children?.length) {
          this.formatTree(item.children)
        }
      })
    },
    handleChange(serviceKey) {
      serviceKey && this.getServiceItem(serviceKey.value)
    },
    async getServiceItem(serviceKey) {
      this.showServiceDetail = false
      const serviceItem = this.serviceListData.services.find(el => el.id === serviceKey)
      serviceItem && (this.serviceItem = serviceItem)
      if (serviceItem) {
        this.getS2_2(serviceItem)
        this.formData.inputParams = adapterServiceItemData(serviceItem)
      }
      this.formData.serviceName = serviceItem.name
      this.formData.serviceKey = serviceItem.identifier
    },
    // 获取S2-2对应服务的小组件配置信息
    async getS2_2(serviceItem) {
      const param = { id: serviceItem.id, terminalType: 0, metamodelParams: [] }
      const addItem = (list) => {
        list.forEach(item => {
          if (item.memberList && item.memberList.length > 1) {
            item.memberList.forEach(member => { member.paramParentId = item.id })
            addItem(item.memberList)
          } else {
            param.metamodelParams.push({ paramDataType: item.category, paramKey: item.identifier, paramParentId: item.paramParentId || '0', paramId: item.id })
          }
        })
      }
      serviceItem.inputData && addItem(serviceItem.inputData)
    },
    // 获取value范围 S2-2优先级大于S8
    computeEdge(componentsProps, member, type) {
      let edge
      if (type === 'min') {
        if (componentsProps && componentsProps.min) {
          edge = componentsProps.min
        } else {
          edge = member.physicalMin !== null ? member.physicalMin : -Infinity
        }
        if (member.calcRelation !== '1') { edge = 0 } // 相对值不考虑S2-2配置
        if (member.value < edge) { member.value = edge }
      } else {
        if (componentsProps && componentsProps.max) {
          edge = componentsProps.max
        } else {
          edge = member.physicalMax !== null ? member.physicalMax : Infinity
        }
        if (member.calcRelation !== '1') { edge = Infinity } // 相对值不考虑S2-2配置
        if (member.value > edge) { member.value = edge }
      }
      return edge
    },
    saveEdit() {
      let validForm = true
      this.$refs.serviceForm.validate(valid => { validForm = valid })
      const validateStructs = (param, ref) => {
        param.memberList.forEach((item, index) => {
          if (item.memberList && !this.componentsProps[item.paramKey]) validateStructs(item, ref.$refs.structItem[index])
          else if (item.memberList && this.componentsProps[item.paramKey]) ref.$refs.structItem[index].$refs.position2D.$refs.structForm.validate(valid => { validForm = validForm && valid })
          else ref.$refs.structItem[index].$refs.structForm.validate(valid => { validForm = validForm && valid })
        })
      }
      const formatSaveData = (list) => {
        list.forEach(item => {
          if (item.memberList) {
            formatSaveData(item.memberList)
          } else {
            item.showParamOpen = false
          }
        })
      }
      // 结构体表单校验
      this.formData.inputParams.forEach((param, index) => {
        if (param.category === 'Struct') {
          const structItem = this.$refs.structItem.find(item => {
            return item.item.paramKey === param.paramKey
          })
          validateStructs(param, structItem)
        }
      })
      if (validForm) {
        if (this.serviceData) {
          // 编辑
          const newVal = deepClone(this.serviceData)
          newVal.metaModelId = this.formData.metaModelId
          newVal.inputParams = this.formData.inputParams
          newVal.serviceName = this.formData.serviceName
          newVal.serviceKey = this.formData.serviceKey
          formatSaveData(newVal.inputParams)
          this.$emit('update:serviceData', newVal)
        } else {
          const newVal = {
            metaModelId: this.formData.metaModelId,
            inputParams: this.formData.inputParams,
            serviceName: this.formData.serviceName,
            serviceKey: this.formData.serviceKey,
            delayType: 'executeStart',
            delayTime: '0'
          }
          formatSaveData(newVal.inputParams)
          this.$emit('addService', newVal)
        }
        this.handleClose()
      }
    },
    paramOpen(item) {
      if (this.serviceItem.optionalFlag === 1) { return this.$message({ type: 'warning', message: '选装服务不支持参数开放' }) }
      item.showParamOpen = !item.showParamOpen
      if (!item.showParamOpen) {
        this.$refs.paramOpen[0].resetForm()
      }
    },
    normalizer(node) {
      const rtn = {
        id: node.id || node.value,
        label: node.name || node.label
      }
      if (node.children && node.children.length > 0) {
        rtn.children = node.children
      } else {
        delete node.children
      }
      return rtn
    },
    // 隐藏下拉框
    hideCalc() {
      setTimeout(() => {
        this.$refs.selectCalc?.forEach(item => {
          item.blur()
        })
      }, 500)
    },
    handleClose() {
      this.$emit('update:show', false)
    },
    ...mapActions('service', ['getService'])
  },
  computed: {
  },
  watch: {
    async show(val) {
      if (val) {
        if (this.serviceData) {
          // 编辑 初始化
          const formatInitData = (list) => {
            list.forEach(item => {
              if (item.memberList) formatInitData(item.memberList)
              else {
                item.showParamOpen = false
              }
            })
          }
          const data = deepClone(this.serviceData)
          formatInitData(data.inputParams)
          this.getServiceItem(data.metaModelId)
          const serviceItem = this.serviceListData.services.find(el => el.id === data.metaModelId)
          this.formData.metaModelId = serviceItem.id
          this.formData.inputParams = data.inputParams.map((item, index) => {
            return {
              paramName: item.paramName,
              paramKey: item.paramKey,
              category: item.category,
              allowEdit: item.allowEdit,
              hasRefSignal: item.hasRefSignal,
              memberList: item.memberList
            }
          })
        } else {
          // 新增信号
          this.formData = {
            inputParams: []
          }
          this.$nextTick(() => this.$refs.serviceForm.clearValidate())
        }
      }
    }
  }
}
</script>

<style lang="scss">
@import "~@/assets/styles/variables.scss";

.service-item-edit {
  // margin-top: $app-header-height;
  box-shadow: none;
  .el-drawer__body{
    display: flex;
    flex-direction: column;
  }
  .server-item-list{
    flex: 1 1 100px;
    overflow-y: auto;
    .el-scrollbar__wrap{
      overflow-x: hidden;
    }
  }
  .service-form{
    padding: 14px 24px 24px;
    overflow: visible;
    .service-cascader{
      display: block;
    }
    .input-number{
      width: 100%;
      .el-input__inner{
        text-align: left;
      }
    }
    .params-item{
      display: flex;
      align-items: flex-end;
      & > span {
        flex: 1 0 auto;
      }
      .params-item-form{
        flex: 1 0 auto;
        margin-bottom: 8px;
      }
      .input-description{
        position: absolute;
        right: 4px;
        font-size: 16px;
        display: block;
        top: 0;
        line-height: 32px;
        color: #a3a3a3;
      }
      .setting-select-label{
        white-space: nowrap;
        position: absolute;
        right: 10px;
        left: 10px;
      }
      .setting-select{
        flex: 0 1 140px;
        position: relative;
        .select-type{
          width: 132px;
        }
      }
      .tool-bar{
        margin-bottom: 8px;
        .signal-open{
          width: 16px;
          height: 32px;
          cursor: pointer;
          margin-left: 24px;
          margin-right: 2px;
          &.true{
            width: 18px;
            margin-right: 0;
          }
        }
      }
    }
  }
  .service-edit-footer{
    height: 64px;
    line-height: 64px;
    padding: 0 24px;
    border-top: 1px solid $--border-color-base;
    text-align: right;
    overflow: hidden;
  }
}
</style>
